/**
 * @file dohome_hal_network.h
 * @brief 网络操作接口
 * 
 * @copyright Copyright(C),2018-2020, dohomeing www.dohome.com
 * 
 */


#ifndef __DOHOME_HAL_NETWORK_H__
#define __DOHOME_HAL_NETWORK_H__

#include <dohome_type.h>
#include <dohome_error_code.h>
#ifdef __cplusplus
    extern "C" {
#endif
#ifdef DOHOME_HAL_NETWORK_ISGLOBAL
#define DOHOME_HAL_NETWORK_GLOBAL_FLAG extern
#else
#define DOHOME_HAL_NETWORK_GLOBAL_FLAG 
#endif

#define DOHOME_TCP_SERVER_MAX_CONN           3
#define DOHOME_TCP_CLI_MAX_CONN              3

#if (defined(DOHOME_CFG_NETWORK_USE_TASK) && DOHOME_CFG_NETWORK_USE_TASK == 1)

enum{
    DOHOME_HTTP_METHOD_GET = 0,
    DOHOME_HTTP_METHOD_POST,
};

enum{
    DOHOME_HTTP_EVENT_ERROR = 0,
    DOHOME_HTTP_EVENT_DNS_GET_IP,
    DOHOME_HTTP_EVENT_CONNECTED,
    DOHOME_HTTP_EVENT_HEADER_SENTED,
    DOHOME_HTTP_EVENT_RECV_HEADER,
    DOHOME_HTTP_EVENT_RECV_DATA,
    DOHOME_HTTP_EVENT_FINISH,
};

/** @brief   This structure defines the httpclient_t structure   */
typedef struct {
    DOHOME_CHAR_T *url;                /**< hTTP or HTTPS port        */
    DOHOME_UINT8_T method;
    DOHOME_CHAR_T *auth_user;                /**< username for basic authentication         */
    DOHOME_CHAR_T *auth_password;            /**< password for basic authentication         */
    DOHOME_CHAR_T *header;                   /**< request custom header     */
    DOHOME_CHAR_T *post_buf;              /**< user data to be posted. */
    DOHOME_UINT16_T post_buf_len;            /**< post data length. */
    DOHOME_CHAR_T *resp_buf;          /**< buffer to store the response body data. */
    DOHOME_UINT16_T resp_buf_len;        /**< response body buffer length. */
    DOHOME_UINT16_T resp_len;          
    void *arg;
    void (*event_cb)(void *arg, DOHOME_UINT8_T event, void *data);
    dohome_op_ret (*connect_cb)(void *arg);
    dohome_op_ret (*recv_cb)(void *arg, DOHOME_CHAR_T *, DOHOME_UINT16_T); 
    dohome_op_ret (*close_cb)(void *arg, DOHOME_UINT16_T); 
} dohome_http_t;

dohome_op_ret dohome_hal_http_connect(dohome_http_t *client);

enum{
    DOHOME_IP_TYPE_IPv4 = 0,
    DOHOME_IP_TYPE_IPv6 = 1,
    DOHOME_IP_TYPE_ANY  = 2,
};

typedef struct {
    DOHOME_CHAR_T *host;
    DOHOME_UINT16_T port;
    DOHOME_UINT8_T ip_type;
    DOHOME_UINT8_T timeout_ms;
    DOHOME_UINT16_T poll_ms;
    void *arg;
    dohome_op_ret (*poll_cb)(void *arg);
    dohome_op_ret (*connect_cb)(void *arg);
    dohome_op_ret (*recv_cb)(void *arg, DOHOME_CHAR_T *, DOHOME_UINT16_T); 
    dohome_op_ret (*disconnect_cb)(void *arg); 
    dohome_op_ret (*send_cb)(void *arg, DOHOME_UINT16_T); 
    dohome_op_ret (*close_cb)(void *arg, DOHOME_UINT16_T); 
} dohome_tcpc_t;

dohome_op_ret dohome_hal_tcpc_create(dohome_tcpc_t *client);
dohome_op_ret dohome_hal_tcpc_delete(dohome_tcpc_t *client);
dohome_op_ret dohome_hal_tcpc_reconnect(dohome_tcpc_t *client);
dohome_op_ret dohome_hal_tcpc_send(dohome_tcpc_t *client, DOHOME_CHAR_T *data, DOHOME_UINT16_T len);


typedef struct {
    DOHOME_CHAR_T *host;
    DOHOME_UINT16_T port;
    DOHOME_UINT8_T ip_type;
    DOHOME_UINT8_T max_client;
    DOHOME_UINT8_T timeout_ms;
    DOHOME_UINT16_T poll_ms;
    void *arg;
    dohome_op_ret (*poll_cb)(void *arg);
    dohome_op_ret (*connect_cb)(void *arg, DOHOME_UINT8_T);
    dohome_op_ret (*recv_cb)(void *arg, DOHOME_UINT8_T, DOHOME_CHAR_T *, DOHOME_UINT16_T); 
    dohome_op_ret (*disconnect_cb)(void *arg, DOHOME_UINT8_T); 
    dohome_op_ret (*send_cb)(void *arg, DOHOME_UINT8_T, DOHOME_UINT16_T); 
} dohome_tcps_t;

dohome_op_ret dohome_hal_tcps_create(dohome_tcps_t *server);
dohome_op_ret dohome_hal_tcps_delete(dohome_tcps_t *server);
dohome_op_ret dohome_hal_tcps_send(dohome_tcps_t *server, DOHOME_UINT8_T client_id, DOHOME_CHAR_T *data, DOHOME_UINT16_T len);

typedef struct {
    DOHOME_UINT8_T ip_type;
    union {
        struct {
            DOHOME_UINT32_T addr;  
        }ip_v4;
        struct {
            DOHOME_UINT32_T addr[4];  
        }ip_v6;
    }addr;
    DOHOME_UINT16_T port;
}dohome_upd_dest_t;

typedef struct {
    DOHOME_CHAR_T *host;
    DOHOME_UINT16_T port;
    DOHOME_UINT8_T ip_type;
    DOHOME_UINT16_T poll_ms;
    void *arg;
    dohome_op_ret (*poll_cb)(void *arg);
    dohome_op_ret (*recv_cb)(void *arg, dohome_upd_dest_t, DOHOME_CHAR_T *, DOHOME_UINT16_T); 
} dohome_udp_t;

dohome_op_ret dohome_hal_udp_listen(dohome_udp_t *udp);
dohome_op_ret dohome_hal_udp_delete(dohome_udp_t *udp);
dohome_op_ret dohome_hal_udp_send(dohome_udp_t *udp, dohome_upd_dest_t dest, DOHOME_CHAR_T *data, DOHOME_UINT16_T len);

#else

typedef enum{
    DOHOME_IP_ADDR_TYPE_IPv4 = 0,
    DOHOME_IP_ADDR_TYPE_IPv6 = 1,
    DOHOME_IP_ADDR_TYPE_ANY  = 2,
}dohome_ip_addr_type_t;

typedef DOHOME_UINT8_T dohome_tcp_conn;
typedef void(*dohome_tcp_server_poll_t)(void *arg,dohome_tcp_conn conn);//the type of arg is dohome_listen_arg,5s 
typedef dohome_op_ret (*dohome_tcp_server_read_cb_t)(void *arg,dohome_tcp_conn conn,DOHOME_CONST void * buf,DOHOME_UINT16_T len);
typedef dohome_op_ret (*dohome_tcp_server_new_conn_cb_t)(void *arg,dohome_tcp_conn conn);
typedef dohome_op_ret (*dohome_tcp_server_conn_closed_cb_t)(void *arg,dohome_tcp_conn conn);
typedef struct{
    DOHOME_CHAR_T                         *hostname;
    DOHOME_UINT16_T                       port;
    dohome_ip_addr_type_t                 addr_type;
    dohome_tcp_server_poll_t              poll_func;
    dohome_tcp_server_read_cb_t           readcb_func;
    dohome_tcp_server_new_conn_cb_t       new_conn_func;
    dohome_tcp_server_conn_closed_cb_t    conn_closed_cb_func;
}dohome_listen_arg;

DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_tcp_server_listen(dohome_listen_arg *arg);
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_tcp_server_send(dohome_listen_arg *arg,dohome_tcp_conn conn,DOHOME_CONST void * buf,DOHOME_UINT16_T len);
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_tcp_server_close_conn(dohome_listen_arg *arg,dohome_tcp_conn conn);
//--------------------------------------------------------------------------------------------

typedef void        (*dohome_tcp_client_poll_t)(void *arg);//the type of arg is dohome_listen_arg,5s 
typedef dohome_op_ret (*dohome_tcp_client_read_cb_t)(void *arg,DOHOME_CONST void * buf,DOHOME_UINT16_T len);
typedef dohome_op_ret (*dohome_tcp_client_connected_cb_t)(void *arg);
typedef dohome_op_ret (*dohome_tcp_client_conn_closed_cb_t)(void *arg);
typedef dohome_op_ret (*dohome_tcp_client_sent_cb_t)(void *arg,DOHOME_UINT16_T len);
typedef struct{
    DOHOME_CHAR_T                         *hostname;
    DOHOME_UINT16_T                       port;
    void                                *arg;
    dohome_ip_addr_type_t                 addr_type;
    dohome_tcp_client_poll_t              poll_func;
    dohome_tcp_client_read_cb_t           readcb_func;
    dohome_tcp_client_connected_cb_t      connetced_func;
    dohome_tcp_client_conn_closed_cb_t    conn_closed_cb_func;
    dohome_tcp_client_sent_cb_t           sent_cb_func;
}dohome_conn_arg;
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_tcp_client_connect(dohome_conn_arg *arg);
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_tcp_client_send(dohome_conn_arg *arg,DOHOME_CONST void * buf,DOHOME_UINT16_T len);
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_tcp_client_close_conn(dohome_conn_arg *arg);

//---------------------------------------------------------------------------------------------
#define DOHOME_UDP_MAX_ADDR_NUM                  10
#define DOHOME_UDP_MAX_NEW                       5
#define DOHOME_UDP_BROADCAST_ADDR                255
#define dohome_udp_handle_t                      DOHOME_UINT8_T
typedef DOHOME_UINT8_T dohome_udp_addr;
typedef dohome_op_ret (*dohome_udp_read_cb_t)(dohome_udp_addr addr,DOHOME_CONST void * buf,DOHOME_UINT16_T len);

typedef struct{
    DOHOME_CHAR_T *ip_str;
    DOHOME_UINT16_T port;
    dohome_udp_read_cb_t readcb_func;
}dohome_udp_arg;
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_udp_new(dohome_udp_handle_t *handle);
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_udp_remove(dohome_udp_handle_t handle);
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_udp_ret(dohome_udp_handle_t handle, dohome_udp_addr addr, DOHOME_CONST void *buf, DOHOME_UINT16_T len);
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_udp_send(dohome_udp_handle_t handle, DOHOME_UINT8_T *ip_str, DOHOME_UINT16_T port, DOHOME_CONST void *buf, DOHOME_UINT16_T len);
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_udp_listen(dohome_udp_handle_t *handle, dohome_udp_arg *arg);
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_remove_addr(dohome_udp_addr addr);
DOHOME_HAL_NETWORK_GLOBAL_FLAG \
    dohome_op_ret dohome_tcp_client_init(void);
#ifdef __cplusplus
}
#endif

#endif

#endif // __TUYA_HAL_NETWORK_H__

